<!--
 * @Description: 表单
 * @Autor: HuiSir<273250950@qq.com>
 * @Date: 2021-11-04 16:39:23
 * @LastEditTime: 2025-06-02 10:54:30
-->
<template>
	<el-form ref="elForm" :model="modelValue" class="edit-form" :inline="inline" :label-width="labelWidth">
		<template v-for="item in options" :key="item.key">
			<el-form-item v-if="!item.hide" :label="item.label" :prop="item.key" :rules="item.rules"
				:label-width="item.labelWidth || labelWidth"
				:style="`--input-width:${getStringWidth(item.inputWidth) || myInputWidth}`">
				<slot v-if="item.slot" :name="item.slot" />
				<template v-else>
					<!-- 日期，这里单独拎出来是因为使用动态组件的话会导致日期弹框BUG -->
					<el-date-picker v-if="item.component == 'date-picker'" v-model="modelValue[item.key]" v-bind="item.props"
						clearable>
					</el-date-picker>
					<!-- radio单选 -->
					<el-radio-group v-else-if="item.component == 'radio'" v-model="modelValue[item.key]">
						<template v-if="item.options">
							<el-radio v-for="option in item.options" :key="option.value" :value="option.value"
								v-bind="item.props">{{ option.label }}</el-radio>
						</template>
					</el-radio-group>
					<!-- 其他 -->
					<component v-else :is="`el-${item.component}`" v-model="modelValue[item.key]" v-bind="item.props" clearable>
						<!-- 下拉框 -->
						<template v-if="item.options">
							<el-option v-for="option in item.options" :key="option.value" :label="option.label"
								:value="option.value"></el-option>
						</template>
					</component>
				</template>
				<span v-if="item.suffix" class="suffix">{{ item.suffix }}</span>
			</el-form-item>
		</template>
		<el-form-item v-if="showSearchBtn">
			<el-button type="primary" @click="$emit('submit')">搜索</el-button>
			<el-button @click="$emit('reset')">重置</el-button>
		</el-form-item>
	</el-form>
</template>

<script lang="ts">
	import { computed, defineComponent, PropType, ref, watch } from 'vue'
	import { IFormOption } from '../types'

	export default defineComponent({
		name: 'Form',
		props: {
			// 是否行内
			inline: {
				type: Boolean,
				require: false,
				default: true,
			},
			// 是否显示搜索按钮
			showSearchBtn: {
				type: Boolean,
				require: false,
				default: true,
			},
			// 表单项配置选项
			options: {
				type: Array as PropType<IFormOption[]>,
				require: true,
				default: () => [],
			},
			// v-model传参写法
			modelValue: {
				type: Object as PropType<Record<string, any>>,
				require: true,
				default: () => ({}),
			},
			labelWidth: {
				type: [String, Number],
				require: false,
				default: 80
			},
			inputWidth: {
				type: [String, Number],
				require: false,
				default: 220
			},
		},
		// `update:modelValue`为`v-model`传参固定事件写法
		emits: ['update:modelValue', 'submit', 'reset'],
		setup(props, { emit }) {
			// 表单对象
			const elForm = ref()

			// 操作父级数据
			watch(props.modelValue, (value : any) => emit('update:modelValue', value), { deep: true })

			const getStringWidth = (width ?: number | string) => {
				if (typeof width === 'number') {
					return width + 'px'
				}
				return width
			}

			const myInputWidth = computed(() => getStringWidth(props.inputWidth))

			return { elForm, getStringWidth, myInputWidth }
		},
	})
</script>

<style scoped lang="scss">
	.edit-form:deep(.el-form-item) {
		.el-form-item__label {
			justify-content: flex-end;
			flex-direction: row-reverse;
		}

		.el-form-item__content {
			width: var(--input-width) !important;

			.suffix {
				margin-left: 8px;
			}

			.el-input,
			.el-input__inner,
			.el-input-number,
			.el-switch {
				max-width: 100%;

				&.el-date-editor--datetimerange {
					width: 350px !important;
				}
			}
		}
	}
</style>